use crate::rtmp::relay::errors::ClientError;
use crate::rtmp::session::client_session::{ClientSession, ClientSessionType};
use streamhub::define::{BroadcastEvent, BroadcastEventReceiver, StreamHubEventSender};
use streamhub::stream::StreamIdentifier;
use tokio::net::TcpStream;

// 拉取客户端结构体
pub struct PullClient {
    // 服务器地址
    address: String,
    // 接收广播事件接收器
    client_event_consumer: BroadcastEventReceiver,
    // 发送流中心事件发送器
    channel_event_producer: StreamHubEventSender,
}

impl PullClient {
    pub fn new(
        address: String,
        consumer: BroadcastEventReceiver,
        producer: StreamHubEventSender,
    ) -> Self {
        Self {
            address,
            client_event_consumer: consumer,
            channel_event_producer: producer,
        }
    }

    // 拉取客户端
    pub async fn run(&mut self) -> Result<(), ClientError> {
        loop {
            // 异步接收广播事件
            let event = self.client_event_consumer.recv().await;

            if let Ok(BroadcastEvent::Subscribe {
                id: _,
                identifier:
                    StreamIdentifier::Rtmp {
                        app_name,
                        stream_name,
                    },
                server_address: _,
                result_sender: _,
            }) = event
            {
                log::info!(
                    "receive pull event, app_name :{}, stream_name: {}",
                    app_name,
                    stream_name
                );
                // 异步连接到指定地址的服务器
                let stream = TcpStream::connect(self.address.clone()).await?;

                let mut client_session = ClientSession::new(
                    stream,
                    ClientSessionType::Pull,
                    self.address.clone(),
                    app_name.clone(),
                    stream_name.clone(),
                    self.channel_event_producer.clone(),
                    0,
                );

                // 使用 tokio 异步执行器生成一个新的任务，在后台运行客户端会话
                tokio::spawn(async move {
                    // 调用客户端会话的 start 方法
                    if let Err(err) = client_session.run().await {
                        log::error!("client_session as pull client start error: {}", err);
                    }
                });
            }
        }
    }
}
